From: Caolán McNamara Date: Sat, 11 Jul 2026 23:36:15 +0000 (+0000) Subject: [PATCH] put calc external data mappings under link update control X-Git-Tag: archive/raspbian/4%25.2.3-2+rpi1+deb13u8^2~11 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=0cc4c7bda2db0e92d0ba2482278fc7b7f1a307b1;p=libreoffice.git [PATCH] put calc external data mappings under link update control register each mapping as a LinkManager link, so its refresh goes through the same update control as sheet links and area links. Wait until after the infobar-controlled update mode is known to update. Signed-off-by: Caolán McNamara Change-Id: I6710d4bdf3de6e002365d75c911b69076a054da8 Reviewed-on: https://gerrit.collaboraoffice.com/c/core/+/7058 Tested-by: Jenkins CPCI Reviewed-by: Miklos Vajna (cherry picked from commit b72d760465c857eb5dd10cdc45b107c49bb0caec) Signed-off-by: Xisco Fauli Reviewed-on: https://gerrit.libreoffice.org/c/core/+/208394 Tested-by: Christian Lohmaier Reviewed-by: Christian Lohmaier Gbp-Pq: Name CVE-2026-63267-1.diff --- diff --git a/sc/inc/datamapper.hxx b/sc/inc/datamapper.hxx index 984e6cc8121..32d610ac3c9 100644 --- a/sc/inc/datamapper.hxx +++ b/sc/inc/datamapper.hxx @@ -96,7 +96,7 @@ public: class SC_DLLPUBLIC ExternalDataMapper { - //ScDocument& mrDoc; + ScDocument& mrDoc; std::vector maDataSources; public: diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 7908be80dcc..0c0a8617798 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -899,6 +899,10 @@ public: SC_DLLPUBLIC ScDBData* GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2); void RefreshDirtyTableColumnNames(); SC_DLLPUBLIC sc::ExternalDataMapper& GetExternalDataMapper(); + /** True when the document holds at least one external data mapping. Checks + without creating the mapper, so it stays cheap for documents that have + none. */ + SC_DLLPUBLIC bool HasDataProviderMappings() const; SC_DLLPUBLIC const ScRangeData* GetRangeAtBlock( const ScRange& rBlock, OUString& rName, bool* pSheetLocal = nullptr ) const; diff --git a/sc/source/core/data/document10.cxx b/sc/source/core/data/document10.cxx index 4c6527304a7..be8f08adaea 100644 --- a/sc/source/core/data/document10.cxx +++ b/sc/source/core/data/document10.cxx @@ -1021,6 +1021,11 @@ sc::ExternalDataMapper& ScDocument::GetExternalDataMapper() return *mpDataMapper; } +bool ScDocument::HasDataProviderMappings() const +{ + return mpDataMapper && !mpDataMapper->getDataSources().empty(); +} + void ScDocument::StoreTabToCache(SCTAB nTab, SvStream& rStrm) const { const ScTable* pTab = FetchTable(nTab); diff --git a/sc/source/core/tool/ddelink.cxx b/sc/source/core/tool/ddelink.cxx index 4c854321509..c66f343cc8a 100644 --- a/sc/source/core/tool/ddelink.cxx +++ b/sc/source/core/tool/ddelink.cxx @@ -17,6 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include #include #include #include @@ -29,6 +30,7 @@ #include #include +#include #include #include #include @@ -125,6 +127,10 @@ void ScDdeLink::Store( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const sfx2::SvBaseLink::UpdateResult ScDdeLink::DataChanged( const OUString& rMimeType, const css::uno::Any & rValue ) { + if (rDoc.GetDocumentShell() + && !rDoc.GetDocumentShell()->GetEmbeddedObjectContainer().getUserAllowsLinkUpdate()) + return SUCCESS; + // we only master strings... if ( SotClipboardFormatId::STRING != SotExchange::GetFormatIdFromMimeType( rMimeType )) return SUCCESS; diff --git a/sc/source/core/tool/webservicelink.cxx b/sc/source/core/tool/webservicelink.cxx index fb5d81afc87..cbb226e240a 100644 --- a/sc/source/core/tool/webservicelink.cxx +++ b/sc/source/core/tool/webservicelink.cxx @@ -7,6 +7,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include #include #include #include @@ -21,6 +22,7 @@ #include #include #include +#include #include #include @@ -36,6 +38,10 @@ ScWebServiceLink::~ScWebServiceLink() {} sfx2::SvBaseLink::UpdateResult ScWebServiceLink::DataChanged(const OUString&, const css::uno::Any&) { + if (pDoc && pDoc->GetDocumentShell() + && !pDoc->GetDocumentShell()->GetEmbeddedObjectContainer().getUserAllowsLinkUpdate()) + return SUCCESS; + aResult.clear(); bHasResult = false; diff --git a/sc/source/filter/xml/xmlmappingi.cxx b/sc/source/filter/xml/xmlmappingi.cxx index 9e9b23e36a9..2048c929d21 100644 --- a/sc/source/filter/xml/xmlmappingi.cxx +++ b/sc/source/filter/xml/xmlmappingi.cxx @@ -111,15 +111,6 @@ ScXMLMappingContext::ScXMLMappingContext( ScXMLImport& rImport, } } -ScXMLMappingContext::~ScXMLMappingContext() -{ - ScDocument* pDoc = GetScImport().GetDocument(); - auto& rDataMapper = pDoc->GetExternalDataMapper(); - auto& rDataSources = rDataMapper.getDataSources(); - if(!rDataSources.empty()) - rDataSources[0].refresh(pDoc, true); -} - uno::Reference SAL_CALL ScXMLMappingContext::createFastChildContext( sal_Int32 nElement, const uno::Reference& /*xAttrList*/) diff --git a/sc/source/filter/xml/xmlmappingi.hxx b/sc/source/filter/xml/xmlmappingi.hxx index cc38d40dbe9..98a74a7eff3 100644 --- a/sc/source/filter/xml/xmlmappingi.hxx +++ b/sc/source/filter/xml/xmlmappingi.hxx @@ -34,8 +34,6 @@ public: ScXMLMappingContext( ScXMLImport& rImport, const rtl::Reference& rAttrList ); - virtual ~ScXMLMappingContext() override; - virtual css::uno::Reference SAL_CALL createFastChildContext( sal_Int32 nElement, const css::uno::Reference& xAttrList) override; diff --git a/sc/source/ui/dataprovider/dataprovider.cxx b/sc/source/ui/dataprovider/dataprovider.cxx index 3c3302c23c5..0a6eab303aa 100644 --- a/sc/source/ui/dataprovider/dataprovider.cxx +++ b/sc/source/ui/dataprovider/dataprovider.cxx @@ -25,6 +25,10 @@ #include #include #include +#include +#include +#include +#include #include using namespace com::sun::star; @@ -187,8 +191,46 @@ const std::vector>& ExternalDataSource:: return maDataTransformations; } -ExternalDataMapper::ExternalDataMapper(ScDocument& /*rDoc*/) - //mrDoc(rDoc) +namespace { + +// A data mapping fetches external data (CSV, HTML, XML) into a sheet. It is +// registered in the LinkManager so it passes through the same link update +// control as sheet links, area links, and external references. The link holds +// the index of its data source in the mapper. That index is stable because +// data sources are only ever appended, never removed. +class ScDataProviderLink final : public sfx2::SvBaseLink +{ + ScDocShell& mrDocShell; + size_t mnSourceIndex; + +public: + ScDataProviderLink(ScDocShell& rDocShell, size_t nSourceIndex) + : sfx2::SvBaseLink(SfxLinkUpdateMode::ONCALL, SotClipboardFormatId::SIMPLE_FILE) + , mrDocShell(rDocShell) + , mnSourceIndex(nSourceIndex) + { + } + + virtual sfx2::SvBaseLink::UpdateResult DataChanged(const OUString&, + const css::uno::Any&) override + { + if (!mrDocShell.GetEmbeddedObjectContainer().getUserAllowsLinkUpdate()) + return SUCCESS; + + ScDocument& rDoc = mrDocShell.GetDocument(); + std::vector& rSources + = rDoc.GetExternalDataMapper().getDataSources(); + if (mnSourceIndex < rSources.size()) + rSources[mnSourceIndex].refresh(&rDoc, true); + + return SUCCESS; + } +}; + +} + +ExternalDataMapper::ExternalDataMapper(ScDocument& rDoc) + : mrDoc(rDoc) { } @@ -199,6 +241,19 @@ ExternalDataMapper::~ExternalDataMapper() void ExternalDataMapper::insertDataSource(const sc::ExternalDataSource& rSource) { maDataSources.push_back(rSource); + + ScDocShell* pDocShell = mrDoc.GetDocumentShell(); + if (!pDocShell) + return; + + sfx2::LinkManager* pLinkManager = mrDoc.GetLinkManager(); + if (!pLinkManager) + return; + + ScDataProviderLink* pLink = new ScDataProviderLink(*pDocShell, maDataSources.size() - 1); + const OUString& rProvider = rSource.getProvider(); + pLinkManager->InsertFileLink(*pLink, sfx2::SvBaseLinkObjectType::ClientFile, + rSource.getURL(), &rProvider, nullptr); } const std::vector& ExternalDataMapper::getDataSources() const diff --git a/sc/source/ui/docshell/docsh4.cxx b/sc/source/ui/docshell/docsh4.cxx index f9744533772..7efc8ffa048 100644 --- a/sc/source/ui/docshell/docsh4.cxx +++ b/sc/source/ui/docshell/docsh4.cxx @@ -500,6 +500,7 @@ void ScDocShell::Execute( SfxRequest& rReq ) rHelpBtn.set_label(GetStandardText(StandardButtonType::Help).replaceFirst("~", "")); rHelpBtn.connect_clicked(LINK(nullptr, LinkHelp, DispatchHelpLinksHdl)); weld::Button& rBtn = pInfoBar->addButton(); + rBtn.set_buildable_name(u"allowupdating"_ustr); rBtn.set_label(ScResId(STR_ENABLE_CONTENT)); rBtn.set_tooltip_text(ScResId(STR_ENABLE_CONTENT_TOOLTIP)); rBtn.connect_clicked(LINK(this, ScDocShell, ReloadAllLinksHdl)); diff --git a/sc/source/ui/docshell/tablink.cxx b/sc/source/ui/docshell/tablink.cxx index 09a5f674089..9a81793c2c7 100644 --- a/sc/source/ui/docshell/tablink.cxx +++ b/sc/source/ui/docshell/tablink.cxx @@ -35,6 +35,7 @@ #include #include #include +#include #include #include diff --git a/sc/source/ui/view/tabvwsh4.cxx b/sc/source/ui/view/tabvwsh4.cxx index 0e5abc8390e..f7908b6a735 100644 --- a/sc/source/ui/view/tabvwsh4.cxx +++ b/sc/source/ui/view/tabvwsh4.cxx @@ -1632,7 +1632,8 @@ void ScTabViewShell::Construct( TriState nForceDesignMode ) if (!bLink) { const sc::DocumentLinkManager& rMgr = rDoc.GetDocLinkManager(); - if (rDoc.HasLinkFormulaNeedingCheck() || rDoc.HasAreaLinks() || rMgr.hasExternalLinks()) + if (rDoc.HasLinkFormulaNeedingCheck() || rDoc.HasAreaLinks() + || rDoc.HasDataProviderMappings() || rMgr.hasExternalLinks()) bLink = true; } if (bLink)